﻿using System.Collections.Generic;
using Microsoft.Xna.Framework;

namespace ProcessManagerXNA.Process
{
    public class ProcessManager : GameComponent
    {
        private readonly List<IProcess> m_processList;

        public ProcessManager(Game game)
            : base(game)
        {
            m_processList = new List<IProcess>();
        }

        ~ProcessManager()
        {
            m_processList.Clear();
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            int i = 0;
            while (i < m_processList.Count)
            {
                IProcess process = m_processList[i];

                if (process.GetState() == ProcessState.UNINITILIZED)
                {
                    process.OnInit();
                }

                if (process.GetState() == ProcessState.RUNNING)
                {
                    process.OnUpdate(gameTime);
                }

                if (process.IsDead())
                {
                    switch (process.GetState())
                    {
                        case ProcessState.SUCCEEDED:
                            {
                                process.OnSuccess();
                                IProcess child = process.RemoveChild();
                                if (child != null)
                                    m_processList.Add(child);
                                break;
                            }

                        case ProcessState.FAILED:
                            {
                                process.OnFail();
                                break;
                            }

                        case ProcessState.ABORTED:
                            {
                                process.OnAbort();
                                break;
                            }
                    }
                    m_processList.Remove(process);
                }
                else
                {
                    ++i;
                }
            }
        }

        public void AttachProcess(IProcess process)
        {
            m_processList.Add(process);
        }

        public void AbortAllProcesses(bool immediate)
        {
            int i = 0;

            while (i < m_processList.Count)
            {
                IProcess process = m_processList[i];
                process.Abort();

                if (immediate)
                {
                    process.OnAbort();
                    m_processList.Remove(process);
                }
                else
                {
                    i++;
                }
            }
        }
    }
}
